package com.chenfengyao.gamereversi.widget

import android.content.Context
import android.media.SoundPool
import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.helper.widget.Flow
import androidx.constraintlayout.widget.ConstraintLayout
import com.chenfengyao.gamereversi.R
import com.chenfengyao.gamereversi.common.CELL_COUNT
import com.chenfengyao.gamereversi.core.ChessPiece
import com.chenfengyao.gamereversi.core.Referee
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class ReversiBoard @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), CoroutineScope by MainScope() {

    private val soundPool = SoundPool.Builder().setMaxStreams(1).build()
    private var soundId = -1


    private val helperFlow = Flow(context, attrs, defStyleAttr)

    private lateinit var referee: Referee

    // 用户点击棋盘的回调
    var onCellClick: ((x: Int, y: Int) -> Unit)? = null

    init {
        val flowParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        addView(helperFlow, flowParams)
        helperFlow.setWrapMode(Flow.WRAP_CHAIN)
        helperFlow.setOrientation(Flow.HORIZONTAL)
        helperFlow.setMaxElementsWrap(CELL_COUNT)
        helperFlow.setVerticalGap(10)
        helperFlow.setHorizontalGap(10)
        helperFlow.setPadding(10)

        val bgView = View(context)
        bgView.setBackgroundResource(R.color.bg_board)
        addView(bgView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))


        launch(Dispatchers.Default) {
            soundId = soundPool.load(context, R.raw.piece_create, 1)
        }

    }

    fun initGame(referee: Referee) {
        this.referee = referee
        referee.init()

        launch {
            referee.boardFlow.collect {
                updateBoard(it)
            }
        }
    }

    fun initBoard() {
        val ids = IntArray(CELL_COUNT * CELL_COUNT)
        repeat(CELL_COUNT * CELL_COUNT) {
            val view = ReversiCell(context)
            view.index = it
            view.setBackgroundResource(R.color.bg_board_item)
            val params = LayoutParams(0, 0)
            view.id = View.generateViewId()

            view.setOnClickListener {
                val tag = view.tag as Int
                val posX = tag % CELL_COUNT
                val posY = tag / CELL_COUNT
                onCellClick?.invoke(posX, posY)
            }

            addView(view, params)
            ids[it] = view.id
            view.tag = it
        }

        helperFlow.setReferencedIds(ids)
    }

    fun playChess(x: Int, y: Int) {
        onCellClick(findViewWithTag(y * CELL_COUNT + x)!!, x, y)
    }

    private fun onCellClick(cell: ReversiCell, x: Int, y: Int) {
        if (!referee.canPlace(x, y)) {
            return
        }
        playSound()
        cell.updateChessPiece(referee.nextPlayer)
        launch {
            val animDeprecated = async {
                delay(300)
            }
            val refereeDeprecated = async {
                referee.onCellClick(x, y)
            }
            animDeprecated.await()
            refereeDeprecated.await()
        }

    }

    private fun updateBoard(board: Array<Array<ChessPiece>>) {
        board.forEachIndexed { x, row ->
            row.forEachIndexed { y, piece ->
                findViewWithTag<ReversiCell>(y * CELL_COUNT + x)?.updateChessPiece(piece)
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        soundPool.release()
    }

    private fun playSound() {
        soundPool.play(soundId, 1f, 1f, 0, 0, 1f)
    }
}